package services

import (
	"fmt"
	"path/filepath"
	"strings"
	"time"

	"go.uber.org/zap"

	"dcarpai-guider/internal/models"
	"dcarpai-guider/internal/utils"
)

// ConfigService 配置服务
type ConfigService struct {
	fileManager *utils.FileManager
	logger      *zap.Logger
	configDir   string
}

// NewConfigService 创建新的配置服务
func NewConfigService(fileManager *utils.FileManager, logger *zap.Logger) *ConfigService {
	return &ConfigService{
		fileManager: fileManager,
		logger:      logger,
		configDir:   "data/configs",
	}
}

// GetAllConfigs 获取所有配置文件列表
func (cs *ConfigService) GetAllConfigs() ([]models.ConfigListItem, error) {
	files, err := cs.fileManager.ListConfigFiles(cs.configDir)
	if err != nil {
		cs.logger.Error("获取配置文件列表失败", zap.Error(err))
		return nil, fmt.Errorf("获取配置文件列表失败: %w", err)
	}

	var configs []models.ConfigListItem
	for i, file := range files {
		// 去掉 .json 扩展名
		name := strings.TrimSuffix(file, ".json")

		config := models.ConfigListItem{
			ID:      i + 1, // 简单的序号作为ID
			Name:    name,
			Created: "2025-01-01T00:00:00Z", // 实际项目中可以读取文件创建时间
		}

		configs = append(configs, config)
	}

	cs.logger.Info("获取配置列表成功", zap.Int("count", len(configs)))
	return configs, nil
}

// GetConfig 获取指定配置
func (cs *ConfigService) GetConfig(name string) (*models.Config, error) {
	// 确保文件名安全，防止路径遍历攻击
	if strings.Contains(name, "..") || strings.Contains(name, "/") {
		return nil, fmt.Errorf("无效的配置文件名")
	}

	configPath := filepath.Join(cs.configDir, name+".json")

	var content map[string]interface{}
	if err := cs.fileManager.ReadJSON(configPath, &content); err != nil {
		cs.logger.Error("读取配置文件失败",
			zap.String("name", name),
			zap.Error(err),
		)
		return nil, fmt.Errorf("读取配置文件失败: %w", err)
	}

	config := &models.Config{
		ID:      1, // 简单处理
		Name:    name,
		Content: content,
		Created: "2025-01-01T00:00:00Z",
	}

	cs.logger.Info("获取配置成功", zap.String("name", name))
	return config, nil
}

// UpdateConfig 更新配置
func (cs *ConfigService) UpdateConfig(req *models.ConfigRequest) (*models.Config, error) {
	// 确保文件名安全
	if strings.Contains(req.Name, "..") || strings.Contains(req.Name, "/") {
		return nil, fmt.Errorf("无效的配置文件名")
	}

	configPath := filepath.Join(cs.configDir, req.Name+".json")

	// 检查配置内容是否有效（简单验证）
	if req.Content == nil {
		return nil, fmt.Errorf("配置内容不能为空")
	}

	// 保存配置
	if err := cs.fileManager.WriteJSON(configPath, req.Content); err != nil {
		cs.logger.Error("保存配置文件失败",
			zap.String("name", req.Name),
			zap.Error(err),
		)
		return nil, fmt.Errorf("保存配置文件失败: %w", err)
	}

	cs.logger.Info("更新配置成功",
		zap.String("name", req.Name),
		zap.String("path", configPath),
	)

	// 返回更新后的配置
	config := &models.Config{
		ID:      1,
		Name:    req.Name,
		Content: req.Content,
		Created: "2025-01-01T00:00:00Z",
		Updated: time.Now().Format(time.RFC3339),
	}

	return config, nil
}

// CreateConfig 创建新配置
func (cs *ConfigService) CreateConfig(req *models.ConfigRequest) (*models.Config, error) {
	// 确保文件名安全
	if strings.Contains(req.Name, "..") || strings.Contains(req.Name, "/") {
		return nil, fmt.Errorf("无效的配置文件名")
	}

	configPath := filepath.Join(cs.configDir, req.Name+".json")

	// 检查文件是否已存在
	if cs.fileManager.FileExists(configPath) {
		return nil, fmt.Errorf("配置文件已存在")
	}

	// 检查配置内容是否有效
	if req.Content == nil {
		return nil, fmt.Errorf("配置内容不能为空")
	}

	// 保存配置
	if err := cs.fileManager.WriteJSON(configPath, req.Content); err != nil {
		cs.logger.Error("创建配置文件失败",
			zap.String("name", req.Name),
			zap.Error(err),
		)
		return nil, fmt.Errorf("创建配置文件失败: %w", err)
	}

	cs.logger.Info("创建配置成功",
		zap.String("name", req.Name),
		zap.String("path", configPath),
	)

	// 返回新创建的配置
	config := &models.Config{
		ID:      1,
		Name:    req.Name,
		Content: req.Content,
		Created: time.Now().Format(time.RFC3339),
	}

	return config, nil
}

// DeleteConfig 删除配置
func (cs *ConfigService) DeleteConfig(name string) error {
	// 确保文件名安全
	if strings.Contains(name, "..") || strings.Contains(name, "/") {
		return fmt.Errorf("无效的配置文件名")
	}

	// 防止删除关键配置文件
	if name == "app" || name == "system" {
		return fmt.Errorf("不能删除系统关键配置文件")
	}

	configPath := filepath.Join(cs.configDir, name+".json")

	// 检查文件是否存在
	if !cs.fileManager.FileExists(configPath) {
		return fmt.Errorf("配置文件不存在")
	}

	// 删除文件
	if err := cs.fileManager.DeleteFile(configPath); err != nil {
		cs.logger.Error("删除配置文件失败",
			zap.String("name", name),
			zap.Error(err),
		)
		return fmt.Errorf("删除配置文件失败: %w", err)
	}

	cs.logger.Info("删除配置成功",
		zap.String("name", name),
		zap.String("path", configPath),
	)

	return nil
}

// ValidateConfig 验证配置格式（根据配置类型进行不同的验证）
func (cs *ConfigService) ValidateConfig(name string, content map[string]interface{}) error {
	switch name {
	case "app":
		return cs.validateAppConfig(content)
	case "system":
		return cs.validateSystemConfig(content)
	default:
		// 对于其他配置文件，只做基本验证
		if len(content) == 0 {
			return fmt.Errorf("配置内容不能为空")
		}
	}

	return nil
}

// validateAppConfig 验证应用配置
func (cs *ConfigService) validateAppConfig(content map[string]interface{}) error {
	required := []string{"app_name", "version", "server"}

	for _, key := range required {
		if _, exists := content[key]; !exists {
			return fmt.Errorf("缺少必需的配置项: %s", key)
		}
	}

	// 验证服务器配置
	if server, ok := content["server"].(map[string]interface{}); ok {
		if _, exists := server["port"]; !exists {
			return fmt.Errorf("服务器配置缺少端口设置")
		}
	} else {
		return fmt.Errorf("服务器配置格式错误")
	}

	return nil
}

// validateSystemConfig 验证系统配置
func (cs *ConfigService) validateSystemConfig(content map[string]interface{}) error {
	// 检查必需的配置项
	if _, exists := content["database"]; !exists {
		return fmt.Errorf("缺少数据库配置")
	}

	if _, exists := content["logging"]; !exists {
		return fmt.Errorf("缺少日志配置")
	}

	return nil
}

// BackupConfig 备份配置文件
func (cs *ConfigService) BackupConfig(name string) error {
	// 确保文件名安全
	if strings.Contains(name, "..") || strings.Contains(name, "/") {
		return fmt.Errorf("无效的配置文件名")
	}

	configPath := filepath.Join(cs.configDir, name+".json")
	backupPath := filepath.Join(cs.configDir, fmt.Sprintf("%s.backup.%s.json",
		name, time.Now().Format("20060102150405")))

	// 读取原配置
	var content map[string]interface{}
	if err := cs.fileManager.ReadJSON(configPath, &content); err != nil {
		return fmt.Errorf("读取配置文件失败: %w", err)
	}

	// 保存备份
	if err := cs.fileManager.WriteJSON(backupPath, content); err != nil {
		return fmt.Errorf("创建备份文件失败: %w", err)
	}

	cs.logger.Info("配置备份成功",
		zap.String("name", name),
		zap.String("backup_path", backupPath),
	)

	return nil
}
